#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <unistd.h>
#include <pthread.h>
#include <panel.h>
#include <ctype.h>

#define TAMANHO_MAXIMO 255
#define MAXIMO_CLIENTS 10
#define MAXIMO_GRUPOS 10

#define PASSWORD "admin"

//mensagens interface
#define BOAS_VINDAS "Encontra-se agora ligado ao servidor. Bem-Vindo!"
#define DESPEDIDA "Encontra-se agora desligado do servidor. Arriverdeci!"
#define SERVIDOR_CHEIO "O servidor já se encontra cheio. Não se pode ligar!"
#define JA_LIGADO "Já se encontra ligado ao servidor!"
#define CLIENT_LIGADO " acabou de se ligar ao servidor!"
#define NAO_LIGADO "Não se encontra ligado ao servidor!"
#define CLIENT_DESLIGADO " acabou de sair do servidor!"
#define COMANDO_INVALIDO "Erro: Comando Inválido!"
#define NICK_INVALIDO "Não foi possivel ligar-se visto que o nick escolhido já está em utilização. Altere o seu nick com o comando '/nick'."
#define NICK_INVALIDO2 "O nick escolhido já se encontra em uso."
#define CLIENT_NOVO_NICK " mudou o nome para "
#define LIGOU_A_GRUPO "Acabou de entrar para o grupo "
#define AVISO_LIGACAO_GRUPO " acabou de entrar para o grupo "
#define USER_INEXISTENTE "Não existe nenhum utilizador com o nick indicado."
#define AVISO_SAIDA_GRUPO " acabou de sair do grupo "
#define SAIU_DO_GRUPO "Acabou de sair do grupo "
#define SAIU_DO_CHAT "Acabou de sair do chat com "
#define GRUPO_INEXISTENTE "O grupo a que se tentou ligar não existe. Para o criar use o comando '/create <nome_do_grupo>'."
#define NOVO_GRUPO "Acabou de criar o grupo "
#define GRUPO_REPETIDO "O grupo que tentou criar já existe. Para se ligar a ele use o comando '/join <nome_do_grupo>'."
#define EM_CHAT "Foi iniciada uma conversa privada. Encontra-se agora em chat privado com o utilizador "
#define AVISO_EXISTENCIA_CHAT " encontra-se agora num chat privado com "
#define NAO_LIGADO_GRUPO "Não se encontra ligado a nenhum grupo."
#define AJUDA "Escreva '/help <comando>'"
#define CHAT_SELF "Não pode iniciar um chat consigo próprio."
#define CHAT_OCUPPIED "Não pode iniciar um chat com este cliente."
#define CHAT_DUP "Não pode iniciar um chat enquanto não terminar este. Use o comando '/leave'"
#define GRUPO_DUP "Não pode criar ou juntar-se a um grupo enquanto não terminar este. Use o comando '/leave'"
#define NUM_CLIENTES "Número de utilizadores actuais: "
#define NUM_LIGACOES "Número de pedidos de ligação: "
#define NUM_MULTI "Número de mensagens trocadas em multicast: "
#define NUM_BROAD "Número de mensagens trocadas em broadcast: "
#define NUM_UNI "Número de mensagens trocadas em unicast: "
#define NUM_BYTES "Número de bytes trocados: "
#define CLI_NUM_MULTI_ENV "Número de mensagens enviadas em multicast: "
#define CLI_NUM_BROAD_ENV "Número de mensagens enviadas em broadcast: "
#define CLI_NUM_UNI_ENV "Número de mensagens enviadas em unicast: "
#define CLI_NUM_MULTI_REC "Número de mensagens recebidas em multicast: "
#define CLI_NUM_BROAD_REC "Número de mensagens recebidas em broadcast: "
#define CLI_NUM_UNI_REC "Número de mensagens recebidas em unicast: "
#define CLI_NUM_BYTES "Número de bytes trocados: "
#define TEMPO_LIG "Duração da ligação actual: "

//mensagens internas
#define DISCONNECT_MESSAGE "*disconnect"
#define CONNECT_MESSAGE "*connect"
#define MUDAR_NICK "*change_nick"
#define JOINED_GROUP "*joined group"
#define CREATED_GROUP "*created group"
#define LEFT_GROUP "*left group"
#define LEFT_CHAT "*left chat"
#define IN_CHAT "*chat"

//comandos implementados
enum COMANDOS {CONNECT, DISCONNECT, WHOIS, MESSAGE, NICK, SILENT, CREATE, LIST_USERS, 
			   LIST_GROUPS, JOIN, MEMBERS, CHAT, LEAVE, MYSTATS, STATS, RT_ON, RT_OFF, EXIT, HELP, KICK, SHUTDOWN, UNDEFINED};
			   
typedef struct {
	char nome[TAMANHO_MAXIMO];
	char email[TAMANHO_MAXIMO];
	char nick[TAMANHO_MAXIMO];
	char info_srv_to_cli[TAMANHO_MAXIMO];
	char msg_srv_to_cli[TAMANHO_MAXIMO];
	char msg_cli_to_srv[TAMANHO_MAXIMO];
	
	char msg[TAMANHO_MAXIMO];
	enum COMANDOS id_comando;
	pid_t pid;
} COMANDO;

typedef struct {
	char nome[TAMANHO_MAXIMO];
	char nick[TAMANHO_MAXIMO];
	char email[TAMANHO_MAXIMO];
	char info_srv_to_cli[TAMANHO_MAXIMO];
	char msg_srv_to_cli[TAMANHO_MAXIMO];
	char msg_cli_to_srv[TAMANHO_MAXIMO];
	pid_t pid;
	int groupID;
	char nick_chat[TAMANHO_MAXIMO];
	int msg_broad_env;
	int msg_multi_env;
	int msg_uni_env;
	int msg_broad_rec;
	int msg_multi_rec;
	int msg_uni_rec;
	int num_bytes;
	time_t tempo;
} CLIENT;

typedef struct {
	char mensagem[TAMANHO_MAXIMO];
	char mensagem_aux[TAMANHO_MAXIMO];
} INFO_TO_CLIENT;

typedef struct {
	char msg[TAMANHO_MAXIMO];
	char nick[TAMANHO_MAXIMO];
} MENSAGEM_FROM_SERVER;
